home *** CD-ROM | disk | FTP | other *** search
Text File | 1988-11-04 | 9.5 KB | 371 lines | [TEXT/EDIT] |
- #! /bin/sh
- # This is a shell archive, meaning:
- # 1. Remove everything above the #! /bin/sh line.
- # 2. Save the resulting text in a file.
- # 3. Execute the file with /bin/sh (not csh) to create the files:
- #
- # number.c
- #
- # This archive created: Tue Oct 18 09:35:23 1988
- # By: Roger L. Long (bytebug@dhw68k.cts.com)
- #
- export PATH; PATH=/bin:$PATH
- echo shar: extracting "'number.c'" '(8687 characters)'
- if test -f 'number.c'
- then
- echo shar: will not over-write existing file "'number.c'"
- else
- sed 's/^X//' << \SHAR_EOF > 'number.c'
- X/*
- X*Program name: Number Talk
- X*
- X*Author: The guts of this program come from an unknown Unix machine.
- X* There was no documentation, so the author is unknown. I did
- X* a quick port to the Mac (and Lightspeed C), and added the
- X* speech feature. Ted C. Johnson, August 10, 1988. As far as
- X* I know, the program is Public Domain (FreeWare). Have fun!
- X*
- X*Compilation instructions: use Lightspeed C, v. 2.15. This program does
- X* NOT use a resource file. It was tested on a
- X* Mac SE HD20, running System/Finder 4.1/5.5.
- X*
- X*Summary: This program translates a number (e.g., -123.454) into English
- X* ("Negative One Hundred Twenty-Three Point Four Five Four"),
- X* and speaks it. Number Talk handles positive and negative
- X* integers and floating point numbers, but does not accept commas.
- X*
- X* Number Talk will translate the number to either a cardinal
- X* number (e.g., 4 becomes "Four") or an ordinal number (e.g.,
- X* 4 becomes "Fourth".
- X*
- X* Type "o" for ordinal mode.
- X* Type "c" for cardinal mode.
- X* Type "q" to quit.
- X* Type a number, hit carriage return, and Number Talk will
- X* spell it and then speak it.
- X*
- X*NOTE: You must have the MacinTalk driver in your System Folder to
- X* run this program!
- X*/
- X
- X#include <stdio.h>
- X#include <strings.h>
- X#include <MacTypes.h>
- X#include <MacinTalk.h>
- X
- X
- X
- X#define TRUE 1
- X#define FALSE 0
- X
- Xchar words[BUFSIZ];
- XStr255 s;
- X
- XSpeechHandle theSpeech;
- XHandle theText;
- X
- X
- X
- Xmain(argc,argv)
- Xint argc;
- Xchar *argv[];
- X{
- Xdouble n; /* Holds number for pass to ftow */
- Xchar *numb; /* Pointer to return from number */
- Xint thend; /* Flag for ordinal numbers */
- Xextern char *ftow();
- Xextern double atof();
- Xint quit = FALSE;
- X
- X thend = FALSE;
- X
- X SpeechOn("",&theSpeech);
- X theText = NewHandle(0);
- X
- X printf("Welcome to \"Number Talk\"\n");
- X say("Welcome to Number Talk", FALSE);
- X say("(a public domain program ported by Ted C Johnson)", TRUE);
- X printf("\n");
- X say("Enter any number, and I will spell it and speak it", TRUE);
- X say("Please don't use commas!", TRUE);
- X say("Type c for cardinal mode", TRUE);
- X say("Type o for ordinal mode", TRUE);
- X say("Type q to quit", TRUE);
- X printf("\n");
- X say("Here we go", TRUE);
- X
- X printf("\n\n");
- X
- X for (;!quit;) {
- X say("Enter a number",FALSE);
- X printf("Enter a number (or a command)-->");
- X gets(s);
- X
- X switch(s[0]) {
- X case 'q':
- X quit = TRUE;
- X break;
- X
- X case 'o':
- X thend = TRUE;/*ordinal numbers wanted*/
- X break;
- X
- X case 'c':
- X thend = FALSE;
- X break;
- X
- X default:
- X n = atof(s); /* Get a float for ftow */
- X numb = ftow(n,thend); /* Generate the words */
- X
- X if (n < 0) {
- X say("negative", FALSE);
- X }
- X
- X say(s, FALSE);
- X say("in words is", FALSE);
- X printf("%s\n",numb); /* Print it */
- X say(numb, FALSE);
- X
- X break;
- X }
- X }/*for*/
- X
- X SpeechOff(theSpeech);
- X}
- X
- X
- X
- Xsay(s, printit)
- XStr255 s;
- Xint printit;
- X{
- X if (printit) {
- X printf("%s\n", s);
- X }
- X Reader(theSpeech, s, (long)strlen(s), theText);
- X MacinTalk(theSpeech, theText);
- X}
- X
- X/* Table for name of each three-digit group */
- Xstatic char *units[] =
- X {
- X " Trillion",
- X " Billion",
- X " Million",
- X " Thousand",
- X "\0\0\0\0\0"
- X };
- X
- X
- X
- X/* Names of numbers that are unique */
- Xstatic char *numbers[] =
- X {
- X "Zero", "One", "Two", "Three", "Four", "Five", "Six", "Seven", "Eight",
- X "Nine", "Ten", "Eleven", "Twelve", "Thirteen", "Fourteen", "Fifteen",
- X "Sixteen", "Seventeen", "Eighteen", "Nineteen", "Twenty",
- X "Thirty", "Forty", "Fifty", "Sixty", "Seventy", "Eighty", "Ninety"
- X };
- X
- X
- X
- X/* Ordinal number coding table */
- Xstatic char *ord[] =
- X {
- X "+th","First","Second","Third","+th","Fifth","+th","+th","+h",
- X "Ninth","+th","+th","+th","+th","+th","+th","+th","+th","+th","+th"
- X };
- X
- X
- X
- X/*
- X*Routine to convert the number to words
- X*Entry:
- X*x = double precision number to convert
- X*ordflag = do you want ordinal numbers? (0 = no, !0 = yes)
- X*Returns:
- X*A character pointer to the words
- X*/
- Xchar *ftow(x,ordflag)
- Xdouble x;
- Xint ordflag;
- X{
- Xregister int i; /* Loop counter */
- Xchar numb[25]; /* Holds printf'ed number */
- Xchar hold[30]; /* Gets 3 digit grouping */
- Xint negflag = FALSE; /* Is number negative? */
- Xint n; /* All around number */
- X
- Xextern void thcon(); /* Convert each thousands group */
- X
- X words[0] = '\0'; /* Initialize for strcat */
- X
- X /* More than one quadrillion */
- X if (x >= 1e15) {
- X strcpy(words,"Overflow");
- X return(words);
- X }
- X
- X /* Just tack "Negative" on, */
- X if (x < 0) {
- X strcpy(words,"Negative ");
- X x = -x; /* and convert the positive */
- X negflag = TRUE; /* But let rest of the routine know */
- X }
- X
- X sprintf(numb,"%23.7f",x); /* Put number into printable form */
- X for (i = 0; numb[i] == ' '; ++i) { /* Tack on leading zeros */
- X numb[i] = '0';
- X }
- X
- X
- X if (x < 1) {
- X strcat(words,numbers[0]); /* Add a "Zero" if it is less than 1 */
- X }
- X else {
- X for (i = 0; i < 5; i++) { /* Loop through each thousands group */
- X sscanf(&numb[i*3],"%3d",&n); /* Get number less than one thousand */
- X thcon(hold,n); /* Convert it */
- X
- X /* If it isn't zero */
- X if (*hold != '\0') {
- X if (words[0] != '\0') { /* If it isn't the first word */
- X if (!negflag) /* If the last word wasn't "Negative" */
- X strcat(words,", "); /* Add a comma */
- X strcat(words,hold); /* Then add the words */
- X negflag = FALSE; /* No more "Negative" */
- X }
- X else {
- X strcpy(words,hold); /* Use copy if it is the first word */
- X }
- X strcat(words,units[i]); /* And tack on the "Million", etc */
- X }
- X }
- X }
- Xsscanf(&numb[16],"%d",&n); /* Check for stuff after the decimal */
- Xif (n != 0) /* If there is stuff */
- X {
- X strcat(words," Point"); /* Add decimal point */
- X for (i = 16; numb[i] != '\0'; i++) /* Get to end of number */
- X ;
- X i--;
- X while (numb[i] == '0') /* Strip off trailing zeros */
- X i--;
- X numb[i+1] = '\0';
- X for (i= 16; numb[i] != '\0'; i++) /* Pull off one digit at a time */
- X {
- X strcat(words," "); /* Add the space */
- X n = numb[i] - '0'; /* And convert to decimal */
- X strcat(words,numbers[n]); /* Tack on the right number */
- X }
- X }
- Xelse /* If there ain't no decimals */
- X {
- X if (ordflag) /* And you want ordinals */
- X {
- X for (i = 0; words[i] != '\0'; ++i) /* Get to end of words */
- X ;
- X i--;
- X if (words[i] == 'y') /* If it is a "Twenty", etc */
- X {
- X words[i] = '\0'; /* Change the "y" to "ieth" */
- X strcat(words,"ieth");
- X }
- X else /* Search for beginning of last word */
- X {
- X while(words[i-1] != ' ' && words[i-1] != '-' && i > 0)
- X i--;
- X for (n = 0; n < 20; n++) /* Find out what the last word is */
- X if (strcmp(&words[i],numbers[n]) == 0)
- X break;
- X if (n > 19) /* If we can't figure out what it is */
- X strcat(words,"th"); /* just add a "th" */
- X else
- X {
- X if (ord[n][0] == '+') /* Plus = cat the rest of the string */
- X strcat(words,&ord[n][1]);
- X else /* Otherwise make an entire replace */
- X {
- X words[i] = '\0';
- X strcat(words,ord[n]);
- X }
- X }
- X }
- X }
- X }
- X
- Xfor (n = 0; ; n = i) /* Divide words up into < 80 byte */
- X { /* sections separated by a newline */
- X for (i = n; i < n+80; ++i)
- X if (words[i] == '\0')
- X return(words);
- X while (words[i] != ' ')
- X --i;
- X words[i] = '\n';
- X }
- X}
- X
- X
- X
- X/*
- X*Routine to convert a number less than one thousand into words. Basic
- X*routine, because all groups of three digits similar.
- X*Entry:
- X*buf = a place to put the converted number
- X*z = the number to convert
- X*Return:
- X*Nothing
- X*/
- X
- Xvoid thcon(buf,z)
- Xregister int z;
- Xchar buf[];
- X{
- Xregister int d; /* The divided down number */
- Xregister int spflag = FALSE; /* Do we need a space catted? */
- X
- X buf[0] = '\0'; /* Initialize */
- X
- X /* Converting zero is easy */
- X if (z != 0) {
- X d = z / 100; /* Find out if we need and hundreds */
- X
- X if (d != 0){
- X strcat(buf,numbers[d]); /* Tack them on */
- X strcat(buf," Hundred");
- X spflag = TRUE; /* Need a space afterward */
- X }
- X
- X z %= 100; /* The < 100 stuff */
- X /* Is there any? */
- X if (z != 0) {
- X if (spflag) { /* Need a separator */
- X strcat(buf," ");
- X }
- X /* Simple "Forty-Four" type construct */
- X if (z > 19) {
- X d = z / 10 + 18; /* Get the "Forty" part into d */
- X z %= 10; /* Get the "Four" part into z */
- X strcat(buf,numbers[d]); /* Cat the stuff */
- X if (z != 0) {
- X strcat(buf,"-");
- X strcat(buf,numbers[z]);
- X }
- X }
- X else { /* Just use "One" to "Nineteen" */
- X strcat(buf,numbers[z]);
- X }
- X }
- X }
- X return;
- X}
- SHAR_EOF
- if test 8687 -ne "`wc -c < 'number.c'`"
- then
- echo shar: error transmitting "'number.c'" '(should have been 8687 characters)'
- fi
- fi # end of overwriting check
- # End of shell archive
- exit 0
-